<?php

/**
 * Albireo Kernel
 *
 * @copyright  Copyright (c) 2010 Albireo Solutions
 * @package    Kernel
 */

namespace KernelModule\LogsModule\PhpModule;

use Nette\Object;
use Nette\Environment;
use Nette\IO\SafeStream;

use KernelModule\LogsModule\PageOutOfBoundsException;
use KernelModule\LogsModule\LogsException;
use KernelModule\LogsModule\LogsHashException;
use KernelModule\LogsModule\LogsInitializeException;
use KernelModule\LogsModule\LogsBluescreenFileException;

/**
 * Kernel PHP Error overview
 *
 * @author Pavel
 */

class Display extends Base {
    public $detailer;
    private $logArray;
    private $eofNext = false;
    private $page;



    /**
     * Sets the class variable logArray. It contains the log headers from the clean log.
     * @return array(array(string)) logArray contains info about all KernelLogs
     */
    public function handleLogs($count, $page, $back) {
        $this->page = $page;
        try {
            $this->initializeLogFile("clean");
            $this->initializeLogFile("hash");
        } catch (LogsInitializeException $e) {
            throw new LogsException($e);
        }
        if ($page < 1) throw new PageOutOfBoundsException(sprintf(_("Accessing negative page %s is forbidden."),$page));

        $this->setExcFileNames();
        $lines = $this->loadCleanLines($count, $page, $back);


        $hashesAndInfos = $this->hash->getFileAsArray();
        $haiArray = array();
        $this->detailer = new Detail();
        foreach ($hashesAndInfos as $hashAndInfo) {
            $hashAndInfoArray = explode("#", $hashAndInfo);
            if ($this->bluescreenExists($hashAndInfoArray[0])) {
                $haiArray[] = array("hash" => $hashAndInfoArray[0], "info" => $hashAndInfoArray[1]);
            }
        }

        foreach ($lines as $line) {
            if (strlen($line) < 22) break; //not a regular line (eof or sth like this). 22=[date] length
            $timestamp = $this->retrieveDate($line);

            $logDate = $this->timestampToLogDate($timestamp);
            $logInfoArray = explode(":", substr($line, 23), 2); //split info
            try {
                $hash = $this->retrieveHash($logInfoArray[1], $haiArray);
            } catch (LogsHashException $e) {
                $hash = "missing";
                //throw new LogsException($e);
            }


            $formatedLog["date"] = date('j.n.Y H:i:s', $timestamp); //add datetime string to the output array
            $formatedLog["type"] = $logInfoArray[0]; // error type
            $formatedLog["headline"] = $logInfoArray[1]; // the rest of the info (file, line ...)
            $formatedLog["hash"] = $hash; // error file hash identifier

            $this->logArray[] = $formatedLog;
        }
        if (empty($this->logArray) && $page != 1) throw new PageOutOfBoundsException(sprintf(_("Accessing empty page %s is forbidden."),$page));
        return $this->logArray;
    }


    /**
     * Gets the number of lines from the PhpClean file and returns them
     * as array.
     *
     * @param <type> $count
     * @param <type> $page
     * @return <type>
     */
    public function loadCleanLines($count, $page, $back) {
        if ($this->clean->getFileSize() - $page <= 0) return array();
        $this->clean->movePointerToPosition($this->clean->getFileSize() - $page); //-1 because of the EOF
        $lines = array();

        if ($back) {
            $this->clean->movePointerToPosition($this->clean->getPointerPosition() + 1);
            for ($ii=0; $ii<$count; $ii++) {
                $lines[] = $this->clean->getCurrentLine();
            }
            $lines = array_reverse($lines);
            $this->clean->movePointerToPosition($this->clean->getPointerPosition() - 1);
        } else {
            for ($ii=0; $ii<$count; $ii++) {
                $lines[] = $this->clean->getCurrentLine();
                $this->clean->movePointerToPosition($this->clean->getPointerPosition() - 1);
                $this->clean->movePointerBeginningCurrent();
                if ($this->clean->getPointerPosition() == 0) {
                    $this->eofNext = true;
                    break;
                }
                $this->clean->movePointerToPosition($this->clean->getPointerPosition() - 1);
            }
        }
        return $lines;
    }

    public function getCleanPointer() {
        return $this->clean->getFileSize() - $this->clean->getPointerPosition();
    }

    public function isEofInTheNextLoad() {
        if ($this->eofNext) return true;
        else return false;
    }


    /**
     * Returns the hash related to the given logInfo. The source is given
     * as array in the second parameter (usually contents of the hash-file).
     *
     * @param string $logInfo is the description of the issue, for example
     *      "Uncaught exception 'Exception' with message '..message..' in /path/to/file:25"
     * @param array(string hash, string info) $hai contains all pairs hash-info from
     *      the hash-file.
     * @return string $hash is the part of the filename describing the log error
     *
     */
    private function retrieveHash($logInfo, $hai) {
        foreach ($hai as $hi) {
            if ($hi["info"] == $logInfo) {
                return $hi["hash"];
            }
        }

        throw new LogsHashException(_("No html page generated by Nette Debug. Or corrupted log directory maybe."));
        //This should never happen, just for sure
    }


    function bluescreenExists($hash) {
        try {
            $this->detailer->getDebugFile($hash);
            return true;
        } catch (LogsBluescreenFileException $e) {
            return false;
        }

    }
}